﻿/// <reference path="../jquery-1.8.2.intellisense.js" />
/**
 * SlideNote - jQuery plugin for slideshow specified by an html template and a Json data array
 * Credits:
 * graphics and animation code is derived from Metro UI CSS Carousel 

 //this version will create only 3 dom elements
 */

; (function ($) {

    //   $.SlideNote = function (element, options) {
    function SlideNote(element, options) {
        // default settings
        var defaults = {
            // auto slide change
            auto: true,
            // slide change period
            period: 6000,
            // animation duration
            duration: 1000,
            // animation effect (fade, slide, switch, slowdown)
            effect: 'slide',
            // animation direction (left, right) for some kinds of animation effect
            direction: 'right',
            // markers below the SlideNote
            markers: 'off',
            // prev and next arrows
            arrows: 'on',
            // stop sliding when cursor over the SlideNote
            stop: 'on'
        };

        var plugin = this;
        // plugin settings
        plugin.settings = {};

        var $element = $(element); //  reference to the jQuery version of DOM element
        var $slides = $element.find('.slides'); //  reference to the jQuery version of parent of all slides element

        var domSlides, // all slides DOM objects
            slideData, //array of all slides   stored as json data
            template, //string that contains html of the template
            currentSlideIndex, // index of current slide as it pertain to  slideData array
            currentDomSlideIndex, // index of current DOM slide, can be 0, 1, 2
            slideInPosition, // slide start position before it's appear
            slideOutPosition, // slide position after it's disappear
            parentWidth,
            parentHeight,
            animationInProgress,
            autoSlideTimer,
            markers,
            stopAutoSlide = false;



        plugin.loadData = function (data) {
            slideData = data;

            domSlides = createSlides(slideData);

            currentSlideIndex = 0;
            currentDomSlideIndex = 1;
            // parent block dimensions
            parentWidth = $element.innerWidth();
            parentHeight = $element.innerHeight();
            // slides positions, used for some kinds of animation
            slideInPosition = getSlideInPosition();
            slideOutPosition = getSlideOutPosition();

            // prepare slide elements
            domSlides.each(function (index, slide) {
                $slide = $(slide);
                
                // disappear all slides, except first
                if (index !==1) {
                    $slide.hide();
                }
            });

            start();

        }



        // initialization
        plugin.init = function () {
            setup();
            if (plugin.settings.source) {
                executeFunctionByName(plugin.settings.source, window, plugin.loadData);
            }

        }






        function setup() {
            plugin.settings = $.extend({}, defaults, options);
            template = $element.find('[data-role=slidetemplate]').detach().html();

            if (plugin.settings.arrows === 'on') {
                // prev next buttons handlers
                $element.find('span.control.left').on('click', function () {
                    changeSlide('left');
                    startAutoSlide();
                });

                $element.find('span.control.right').on('click', function () {
                   
                    changeSlide('right');
                    startAutoSlide();
                });
            } else {
                $element.find('span.control').hide();
            }

            // markers
            if (plugin.settings.markers === 'on') {
                insertMarkers();
            }

        }

        function start() {
            if (plugin.settings.auto === true) {
                startAutoSlide();

                // stop sliding when cursor over the SlideNote
                if (plugin.settings.stop === 'on') {
                    $element.on('mouseenter', function () {
                        stopAutoSlide = true;
                    });
                    $element.on('mouseleave', function () {
                        stopAutoSlide = false;
                        startAutoSlide();
                    });
                }
            }
        }

        //clear

        //crete array of 3 slides and attaches them to DOM
        function createSlides(  slideData) {
            var $slide;
            $slides.empty();
            if (slideData.length == 0) {
                $slides.append($('<div><h3>Sorry,  no such records.</h3></div>').addClass('slide').css("top", "45%").css("left", "30%"))
            } else if (slideData.length == 1) {
                $slide = dataToSlide(template, slideData[0]);
                $slide = dataToSlide(template, slideData[0]);
                $slide = dataToSlide(template, slideData[0]);
                parent.append($slide)

            } else {
                $slide = dataToSlide(template, slideData[slideData.length-1]);
                $slide = dataToSlide(template, slideData[0]);
                $slide = dataToSlide(template, slideData[1]);
                $slides.append($slide)
                 
            }

            return $slides.children();
        }

        function updateDomSlides() {
            if (currentDomSlideIndex == 2) {
                $slides.children(".slide").first().remove();
                $slides.append(dataToSlide(template, slideData[getNextSlideIndex()]));
                currentDomSlideIndex = 1;
            } else if (currentDomSlideIndex == 0) {
                $slides.children(".slide").last().remove();
                $slides.prepend(dataToSlide(template, slideData[getNextSlideIndex(true)]));
                currentDomSlideIndex = 1;
            } else {
                return;
            }

        }

        function getNextSlideIndex(reverse) {
            var delta = 1,
                nextSlideIndex;

            if (plugin.settings.direction === 'left') {
                delta = -1;
            }
            nextSlideIndex = !reverse ? currentSlideIndex + delta : currentSlideIndex - delta;

            if (nextSlideIndex >= slideData.length) {
                nextSlideIndex = 0;
            }
            if (nextSlideIndex < 0) {
                nextSlideIndex = slideData.length - 1;
            }

            return nextSlideIndex;

        }

        

        //create one slide from template and data 
        function dataToSlide(template, entity) {
            var html = template.toString(),
                 $slide;

            for (var prop in entity) {

                if (entity.hasOwnProperty(prop)) {

                    var rex = new RegExp("{{\\s*" + prop + "\\s*}}", "ig");
                    html = html.replace(rex, entity[prop]);

                }

            }

            $slide = $(html);
            // each slide must have position:absolute
            // if not, set it
            if ($slide.css('position') !== 'absolute') {
                $slide.css('position', 'absolute');
            }
            return $slide;

        }

        /**
         * returns start position for appearing slide {left: xxx}
         */
        var getSlideInPosition = function () {
            var pos;
            if (plugin.settings.direction === 'right') {
                pos = {
                    left: parentWidth,
                    opacity: 1
                }
            } else if (plugin.settings.direction ==='left' ) {
                pos = {
                    left: -parentWidth,
                    opacity: 1
                }
            }
            return pos;
        };

        /**
         * returns end position of disappearing slide {left: xxx}
         */
        var getSlideOutPosition = function () {
            var pos;
            if (plugin.settings.direction === 'right') {
                pos = {
                    left: -parentWidth,
                    opacity: 0
                }
            } else if (plugin.settings.direction === 'left') {
                pos = {
                    left: parentWidth,
                    opacity: 0
                }
            }
            return pos;
        };

        /**
         * start or restart auto change
         */
        var startAutoSlide = function () {
            clearInterval(autoSlideTimer);
            // start slide changer timer
            autoSlideTimer = setInterval(function () {
                if (stopAutoSlide) {
                    return;
                }
                changeSlide();
            }, plugin.settings.period);
        };

        /**
         * inserts markers below the SlideNote

         NOT TESTED YET
         */
        var insertMarkers = function () {
            var div, ul, li, i;

            div = $('<div class="markers"></div>');
            ul = $('<ul></ul>').appendTo(div);

            for (i = 0; i < slideData.length; i++) {
                li = $('<li><a href="javascript:void(0)" data-num="' + i + '"></a></li>');
                if (i === 0) {
                    li.addClass('active');
                }
                li.appendTo(ul);
            }

            markers = ul.find('li');

            ul.find('li a').on('click', function () {
                var $this = $(this),
                    index;

                // index of appearing slide
                index = $this.data('num');
                if (index === currentSlideIndex) {
                    return;
                }

                changeSlideSwitch(index);
                startAutoSlide();
            });

            div.appendTo($element);
        };

        /**
         * changes slide to next
         */
        var changeSlide = function (direction, effect, slideIndex) {

            if (slideData.length == 1) {
                return;
            }

            var outSlide, // disappearin slide element
                inSlide, // appearing slide element
                nextSlideIndex,
                nextDomSlideIndex
                delta = 1,
                slideDirection = 1;

            effect = effect || plugin.settings.effect;
            // correct slide direction, used for 'slide' and 'slowdown' effects
            if ((effect === 'slide' || effect === 'slowdown') && typeof direction !== 'undefined' && direction !== plugin.settings.direction) {
                slideDirection = -1;
            }
            if (direction === 'left') {
                delta = -1;
            }

            outSlide = $(domSlides[1]);

            nextDomSlideIndex = currentDomSlideIndex + delta;
            nextSlideIndex =  getNextSlideIndex();
            

            inSlide = $(domSlides[1+delta]);

            if (animationInProgress === true) {
                return;
            }

            // switch effect is quickly, no need to wait
            if (effect !== 'switch') {
                // when animation in progress no other animation occur
                animationInProgress = true;
                setTimeout(function () {
                    animationInProgress = false;
                }, plugin.settings.duration)
            }
            currentSlideIndex = nextSlideIndex;
            currentDomSlideIndex = nextDomSlideIndex;

            // change slide with selected effect
            switch (effect) {                
                case 'slide':
                    changeSlideSlide(outSlide, inSlide, slideDirection);
                    break;
                case 'fade':
                    changeSlideFade(outSlide, inSlide);
                    break;
                case 'slowdown':
                    changeSlideSlowdown(outSlide, inSlide, slideDirection);
                    break;
            }

            

            // switch marker
            if (plugin.settings.markers === 'on') {
                markers.removeClass('active');
                $(markers.get(currentSlideIndex)).addClass('active');
            }

        };
        /**
         * switch effect
         */
        var changeSlideSwitch = function (index) {
            outSlide.hide($(domSlides[1]),
                function () {
                    $slides.empty();
                    currentSlideIndex = index;
                    $slides.append(dataToSlide(template, slideData[getNextSlideIndex(true)]));
                    $slides.append(dataToSlide(template, slideData[currentSlideIndex]));
                    $slides.append(dataToSlide(template, slideData[getNextSlideIndex()]));
                    currentDomSlideIndex = 1;                
            });
        };
        /**
         * slide effect
         */
        var changeSlideSlide = function (outSlide, inSlide, slideDirection) {
            var unmovedPosition = { left: 0, opacity: 1 },
                duration = plugin.settings.duration;

            if (slideDirection !== -1) {
                inSlide.css(slideInPosition);
                inSlide.show();
                outSlide.animate(slideOutPosition, duration, updateDomSlides);

                inSlide.animate(unmovedPosition, duration);
            } else {
                inSlide.css(slideOutPosition);
                inSlide.show();
                outSlide.animate(slideInPosition, duration);

                inSlide.animate(unmovedPosition, duration, updateDomSlides);
            }
        };
        /**
         * slowdown slide effect (custom easing 'doubleSqrt')
         */
        var changeSlideSlowdown = function (outSlide, inSlide, slideDirection) {
            var unmovedPosition = { 'left': 0 },
                options;

            options = {
                'duration': plugin.settings.duration,
                'easing': 'doubleSqrt'
            };

            if (slideDirection !== -1) {
                inSlide.css(slideInPosition);
                inSlide.show();
                outSlide.animate(slideOutPosition, options);
                inSlide.animate(unmovedPosition, options, updateDomSlides);
            } else {
                inSlide.css(slideOutPosition);
                inSlide.show();
                outSlide.animate(slideInPosition, options);
                inSlide.animate(unmovedPosition, options, updateDomSlides);
            }
        };
        /**
         * fade effect
         */
        var changeSlideFade = function (outSlide, inSlide) {
            inSlide.fadeIn(plugin.settings.duration);
            outSlide.fadeOut(plugin.settings.duration, updateDomSlides);
        };

        function executeFunctionByName(functionName, context /*, args */) {
            var args = Array.prototype.slice.call(arguments).splice(2);
            var namespaces = functionName.split(".");
            for (var i = 0; i < namespaces.length; i++) {
                context = context[namespaces[i]];
            }
            return context.apply(this, args);
        }

        plugin.init();

    };





    $.fn.SlideNote = function (options) {
        return this.each(function () {
            if (undefined == $(this).data('SlideNote')) {
                var plugin = new SlideNote(this, options);
                $(this).data('SlideNote', plugin);
            }
        });
    };

    // easing effect for jquery animation
    $.easing.doubleSqrt = function (t, millisecondsSince, startValue, endValue, totalDuration) {
        var res = Math.sqrt(Math.sqrt(t));
        return res;
    };



})(jQuery);


$(window).ready(function () {
    var allSlideNotes = $('[data-role=slidenote]');
    allSlideNotes.each(function (index, SlideNote) {
        var params = {};
        $SlideNote = $(SlideNote);
        params.source = $SlideNote.data('source');
        params.sourceBack = $SlideNote.data('sourceBack');
        params.auto = $SlideNote.data('paramAuto');
        params.period = $SlideNote.data('paramPeriod');
        params.duration = $SlideNote.data('paramDuration');
        params.effect = $SlideNote.data('paramEffect');
        params.direction = $SlideNote.data('paramDirection');
        params.markers = $SlideNote.data('paramMarkers');
        params.arrows = $SlideNote.data('paramArrows');
        params.stop = $SlideNote.data('paramStop');

        $SlideNote.SlideNote(params);
    })

});